package com.xmjs.baselibrary.base.activity.lib;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.provider.Settings;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import androidx.annotation.IdRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.xmjs.baselibrary.R;
import com.xmjs.baselibrary.base.activity.systembar.SystemBarActivity;
import com.xmjs.baselibrary.broadcast.AppFrontBackReceiver;
import com.xmjs.baselibrary.broadcast.NetBroadcastReceiver;
import com.xmjs.baselibrary.listener.OnNotificationPermissionsListener;
import com.xmjs.baselibrary.listener.OnVolumeListener;
import com.xmjs.baselibrary.listener.OnWlanSleepStateListener;
import com.xmjs.baselibrary.utils.enums.WlanState;

import java.util.List;

import static com.xmjs.baselibrary.broadcast.AppFrontBackReceiver.APP_BACT_TO_FRONT;
import static com.xmjs.baselibrary.broadcast.AppFrontBackReceiver.APP_FRONT_TO_BACK;

/**
 * 该基类的作用：
 * 1.保持/取消屏幕常亮状态
 * 2.隐藏和显示组件
 * 3.Fragment的添加/替换/显示/隐藏操作
 * 4.监听网络状态
 * 5.监听APP前后台切换
 * 6.检查系统音量
 * 7.检查是否启用通知使用权
 */
public abstract class LibBaseActivity extends SystemBarActivity {
    private PowerManager pm;

    private PowerManager.WakeLock wl;

    private NetBroadcastReceiver netBroadcastReceiver;

    private AppFrontBackReceiver appFrontBackReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //管理屏幕常亮状态
        pm = (PowerManager) getSystemService(POWER_SERVICE);
        wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, getResources().getString(R.string.app_name));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (netBroadcastReceiver != null)
            unregisterReceiver(netBroadcastReceiver);

        if (appFrontBackReceiver != null)
            unregisterReceiver(appFrontBackReceiver);
    }

    /**
     * 屏幕常亮
     */
    public void bright() {
        try {
            wl.acquire();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 取消常亮
     */
    public void cancelBright() {
        try {
            wl.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加 fragment
     *
     * @param idRes    容器ID
     * @param fragment 待添加的 fragment
     */
    public void addFragment(@IdRes int idRes, Fragment fragment) {
        if (!fragment.isAdded()) {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.add(idRes, fragment);
            ft.commit();
        }
    }

    /**
     * 替换 fragment
     *
     * @param idRes    容器ID
     * @param fragment 待替换的 fragment
     */
    public void replaceFragment(@IdRes int idRes, Fragment fragment) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(idRes, fragment);
        ft.commit();
    }

    /**
     * 隐藏 fragment
     *
     * @param fragment
     */
    public void hideFragment(Fragment fragment) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.hide(fragment);
        ft.commit();
    }

    /**
     * 显示 fragment
     *
     * @param fragment
     */
    public void showFragment(Fragment fragment) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.show(fragment);
        ft.commit();
    }

    /**
     * 设置当前Fragment
     *
     * @param id
     * @param fragment
     */
    public void setCurrentFragment(int id, Fragment fragment) {
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        if (!fragment.isAdded())
            fragmentTransaction.add(id, fragment, fragment.toString());
        for (int i = 0; i < fragments.size(); i++) {
            Fragment f = fragments.get(i);
            if (!f.getTag().equals(fragment.getId() + ""))
                fragmentTransaction.hide(f);
        }
        fragmentTransaction.show(fragment);
        fragmentTransaction.commitAllowingStateLoss();
        getSupportFragmentManager().executePendingTransactions();
    }

    /**
     * 显示试图
     *
     * @param views
     */
    public void visible(View... views) {
        for (int i = 0; i < views.length; i++) {
            views[i].setVisibility(View.VISIBLE);
        }
    }

    /**
     * 隐藏视图
     *
     * @param views
     */
    public void invisible(View... views) {
        for (int i = 0; i < views.length; i++) {
            views[i].setVisibility(View.INVISIBLE);
        }
    }

    /**
     * 隐藏视图
     *
     * @param views
     */
    public void gone(View... views) {
        for (int i = 0; i < views.length; i++) {
            views[i].setVisibility(View.GONE);
        }
    }

    /**
     * 获得当前可视的Fragment
     *
     * @return
     */
    @SuppressLint("RestrictedApi")
    public Fragment getVisibleFragment() {
        FragmentManager fragmentManager = getSupportFragmentManager();
        List<Fragment> fragments = fragmentManager.getFragments();
        for (Fragment fragment : fragments) {
            if (fragment != null && fragment.isVisible())
                return fragment;
        }
        return null;
    }

    /**
     * 注册监听网络的广播
     *
     * @param listener
     */
    public void registerNetBroadcastReceiver(NetBroadcastReceiver.OnNetworkListener listener) {
        netBroadcastReceiver = new NetBroadcastReceiver(listener);
        IntentFilter netFilter = new IntentFilter();
        netFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(netBroadcastReceiver, netFilter);
    }

    /**
     * 注册监听APP前后台切换的广播
     *
     * @param listener
     */
    public void registerAppFrontBackReceiver(AppFrontBackReceiver.OnAppStatusListener listener) {
        appFrontBackReceiver = new AppFrontBackReceiver(listener);
        IntentFilter frontFilter = new IntentFilter();
        frontFilter.addAction(APP_FRONT_TO_BACK);
        frontFilter.addAction(APP_BACT_TO_FRONT);
        registerReceiver(appFrontBackReceiver, frontFilter);
    }

    /**
     * 忽略电池优化
     *
     * @param activity
     */
    public void ignoreBatteryOptimization(Activity activity) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
            boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(activity.getPackageName());
            //  判断当前APP是否有加入电池优化的白名单，如果没有，弹出加入电池优化的白名单的设置对话框。
            if (!hasIgnored) {
                Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + activity.getPackageName()));
                if (intent != null)
                    startActivity(intent);
            }
        }
    }

    /**
     * 检查是否开启通知使用权
     *
     * @param listener
     */
    public void checkNotificationPermissions(OnNotificationPermissionsListener listener) {
        boolean enable = false;
        String packageName = getPackageName();
        String flat = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners");
        if (flat != null)
            enable = flat.contains(packageName);
        if (listener != null)
            listener.onNotificationPermissions(enable);
    }

    /**
     * 检查多媒体音量
     *
     * @param listener
     */
    public void checkVolume(OnVolumeListener listener) {
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        if (listener != null)
            listener.onVolume(curVolume, maxVolume);
    }

    /**
     * 检查WLAN在休眠状态下的设置
     *
     * @param listener
     */
    public void checkWlanSleepState(OnWlanSleepStateListener listener) {
        int wlanSleepState = Settings.System.getInt(getContentResolver(),
                android.provider.Settings.System.WIFI_SLEEP_POLICY,
                Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
        if (listener != null)
            if (wlanSleepState == 0) {//永不
                listener.onWlanSleepState(WlanState.NEVER);
            } else if (wlanSleepState == 1) {//仅限充电时
                listener.onWlanSleepState(WlanState.CHARGING);
            } else if (wlanSleepState == 2) {//始终
                listener.onWlanSleepState(WlanState.ALAWS);
            }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View v = getCurrentFocus();//得到当前页面的焦点,ps:有输入框的页面焦点一般会被输入框占据
            if (isShouldHideKeyboard(v, ev)) { //判断用户点击的是否是输入框以外的区域
                hideKeyboard(v.getWindowToken());//收起键盘
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 是否需要收起输入法
     *
     * @param v
     * @param event
     * @return
     */
    private boolean isShouldHideKeyboard(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {//判断得到的焦点控件是否包含EditText
            int[] l = {0, 0};
            v.getLocationInWindow(l);
            //得到输入框在屏幕中上下左右的位置
            int left = l[0];
            int top = l[1];
            int bottom = top + v.getHeight();
            int right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
                //点击位置如果是EditText的区域，忽略它，不收起键盘。
                return false;
            } else {
                return true;
            }
        }
        // 如果焦点不是EditText则忽略
        return false;
    }

    /**
     * 收起输入法
     *
     * @param token
     */
    protected void hideKeyboard(IBinder token) {
        if (token != null) {
            InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }
}
